package org.msgcenter.mc.actor;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.eventbus.Message;
import io.vertx.core.eventbus.MessageConsumer;
import org.msgcenter.mc.common.JsonResult;
import org.msgcenter.mc.ds.TplDto;
import org.msgcenter.mc.ds.TplRequestMsg;

import java.util.List;
import java.util.Map;

/**
 * 模板相关处理器
 */
public class MsgTemplateActor extends AbstractVerticle {

  private EventBus eb;

  private final TemplateEngine engine = TemplateUtil.createEngine();

  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    super.start(startPromise);

    eb = vertx.eventBus();

    onRender();
    onCheckTpl();
  }

  @Override
  public void stop(Promise<Void> stopPromise) throws Exception {
    super.stop(stopPromise);
  }

  // 渲染模板
  private void onRender() {
    MessageConsumer<String> consumer = eb.consumer("service.tpl.render");

    consumer.handler(payload -> {
      TplRequestMsg req = JSONUtil.toBean(payload.body(), TplRequestMsg.class);

      Future<Message<TplDto>> future;
      // 根据不同条件执行不同的查询
      if (StrUtil.isNotBlank(req.getTplCode())) {
        future = eb.request("db.get.select_tpl_by_code", JSONUtil.toJsonStr(req));
      } else {
        future = eb.request("db.get.select_tpl_by_id", req.getId());
      }

      future.onSuccess(r -> {
        Object rData = r.body();
        JsonResult<String, TplDto> jr = JSONUtil.toBean(rData.toString(), new TypeReference<>() {
        }, true);

        if (jr.isOk()) {
          // 渲染
          Template template = engine.getTemplate(jr.getData().getTplContent());
          Map<String, String> map = JSONUtil.toBean(req.getTplContent(), new TypeReference<>() {
          }, true);
          String renderStr = template.render(map);

          JsonResult<String, String> result = new JsonResult<>(HttpStatus.HTTP_OK, "渲染模板成功", renderStr);
          payload.reply(JSONUtil.toJsonStr(result));
        } else {
          JsonResult<String, String> result = new JsonResult<>(0, "渲染模板错误", jr.getMsg());
          payload.reply(JSONUtil.toJsonStr(result));
        }
      });
    });
  }

  // 检查模板内容
  private void onCheckTpl() {
    MessageConsumer<String> consumer = eb.consumer("service.tpl.check_by_id");

    consumer.handler(payload -> {
      TplRequestMsg req = JSONUtil.toBean(payload.body(), TplRequestMsg.class);

      eb.request("db.get.select_tpl_by_id", req.getId())
        .onSuccess(pay -> {
          JsonResult<String, TplDto> jr = JSONUtil.toBean(pay.body().toString(), new TypeReference<>() {
          }, false);

          if (jr.isOk()) {
            TplDto dto = jr.getData();

            // 检查模板字符串字段是否遗漏
            List<String> keys = ReUtil.findAll("\\$\\{([a-z]+)\\}", dto.getTplContent(), 1);
            Map<String, String> map = JSONUtil.toBean(req.getTplContent(), new TypeReference<>() {
            }, true);
            if (!map.keySet().containsAll(keys)) {
              payload.reply(JSONUtil.toJsonStr(new JsonResult<>(0, "发送内容中缺少模板关键字段", req.getTplContent())));
            } else {
              payload.reply(JSONUtil.toJsonStr(new JsonResult<>(HttpStatus.HTTP_OK, "模板id和模板内容完整", Boolean.TRUE)));
            }
          } else {
            payload.reply(JSONUtil.toJsonStr(new JsonResult<>(0, "没有相关模板id内容", req.getId())));
          }
        });
    });

  }
}
